#include "bcmc_rte.h"
#include "application.h"
#include <windows.h>

class Window
{
	cnc::rtl::BCMI_EnvironmentEntities *rte_;
	static char szClassName_[];
	HWND hwnd_;
	static bool registerClass(cnc::rtl::BCMI_EnvironmentEntities *rte);
	static LRESULT CALLBACK procedure(HWND, UINT, WPARAM, LPARAM);
public:
	Window(cnc::rtl::BCMI_EnvironmentEntities *rte);
};

char Window::szClassName_[] = "WindowsApp";

bool Window::registerClass(cnc::rtl::BCMI_EnvironmentEntities *rte)
{
	static bool registered = false;
	if (registered == true)
		return true;
	WNDCLASSEX wndclass;
	wndclass.hInstance = rte->getInstanceHandle();
	wndclass.lpszClassName = reinterpret_cast<LPCTSTR>(szClassName_);
	wndclass.lpfnWndProc = procedure;      /* This function is called by windows */
	wndclass.style = CS_DBLCLKS;           /* Catch double-clicks */
	wndclass.cbSize = sizeof(WNDCLASSEX);
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.lpszMenuName = NULL;                 /* No menu */
	wndclass.cbClsExtra = 0;                      /* No extra bytes after the window class */
	wndclass.cbWndExtra = 0;                      /* structure or the window instance */
	wndclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
	return registered = RegisterClassEx(&wndclass) == TRUE;
}

/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK Window::procedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {          /* handle the messages */
	case WM_DESTROY:
		PostQuitMessage(0); /* send a WM_QUIT to the message queue */
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

Window::Window(cnc::rtl::BCMI_EnvironmentEntities *rte) : rte_(rte)
{
	registerClass(rte);
	hwnd_ = CreateWindowEx(
	        0,                   /* Extended possibilites for variation */
	        reinterpret_cast<LPCTSTR>(szClassName_), /* Class name */
	        TEXT("Runtime Environment Test"), /* Title Text */
	        WS_OVERLAPPEDWINDOW, /* default window */
	        CW_USEDEFAULT,       /* Windows decides the position */
	        CW_USEDEFAULT,       /* where the window ends up on the screen */
	        CW_USEDEFAULT,       /* The programs width */
	        CW_USEDEFAULT,       /* and height in pixels */
	        HWND_DESKTOP,        /* The window is a child-window to desktop */
	        NULL,                /* No menu */
	        rte_->getInstanceHandle(), /* Program Instance handler */
	        NULL                 /* No Window Creation data */
	);
	ShowWindow(hwnd_, rte_->getCmdShow());
}

class RuntimeEnvironmentTest : public cnc::rtl::Application
{
public:
	int main()
	{
		bcm::ComponentManager &compMgr = bcm::ComponentManager::instance();
		bcm::Component *component;
		switch (compMgr.getComponent("rte", &component)) {
		case bcm::GC_UNREGISTERED:
			MessageBox(NULL, TEXT("Component \"rte\" was never registered."),
				TEXT("Critical Error"), MB_OK);
			return 1;
		case bcm::GC_NOCOMPONENT:
			MessageBox(NULL, TEXT("Component \"rte\" not available in DLL."),
				TEXT("Critical Error"), MB_OK);
			return 1;
		case bcm::GC_INCOMPLETE:
			MessageBox(NULL, TEXT("Component \"rte\" incomplete."),
				TEXT("Critical Error"), MB_OK);
			return 1;
		case bcm::GC_OK:
	#ifdef _DEBUG
			MessageBox(NULL, TEXT("Component \"rte\" properly loaded."),
				TEXT("FYI"), MB_OK);
	#endif // _DEBUG
			break;
		}
		bcm::Interface *iface;
		iface = component->getInterface("enventities");
		if (iface == 0) {
			MessageBox(NULL, TEXT("Could not get interface Environment Entities."),
				TEXT("Critical Error"), MB_OK);
			return 1;
		}
		cnc::rtl::BCMI_EnvironmentEntities *env = dynamic_cast<cnc::rtl::BCMI_EnvironmentEntities *>(iface);
		if (env == 0) {
			MessageBox(NULL, TEXT("Retrieved interface is not Environment Entities."),
				TEXT("Critical Error"), MB_OK);
			return 1;
		}
		Window window(env);
		MSG messages;
		/* Run the message loop. It will run until GetMessage() returns 0 */
		while (GetMessage(&messages, NULL, 0, 0)) {
			/* Translate virtual-key messages into character messages */
			TranslateMessage(&messages);
			/* Send message to WindowProcedure */
			DispatchMessage(&messages);
		}

		/* The program return-value is 0 - The value that PostQuitMessage() gave */
		return messages.wParam;
	}
} application;

